package file_info

import "syscall"

type fileStat struct {
	CreationTime   syscall.Filetime
	LastAccessTime syscall.Filetime
	LastWriteTime  syscall.Filetime
	FileSizeHigh   uint32
	FileSizeLow    uint32
	Nlink          uint32

	vol   uint32
	idxhi uint32
	idxlo uint32
}

func (s *fileStat) size() int64 {
	return int64(s.FileSizeHigh)<<32 + int64(s.FileSizeLow)
}

func (s *fileStat) devNum() uint32 {
	return s.vol
}

func stat(filename string) (*fileStat, error) {
	filename16, err := syscall.UTF16PtrFromString(filename)
	if err != nil {
		return nil, err
	}
	h, err := syscall.CreateFile(filename16, 0, 0, nil, syscall.OPEN_EXISTING, uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS), 0)
	if err != nil {
		return nil, err
	}
	defer syscall.CloseHandle(h)
	var i syscall.ByHandleFileInformation
	if err := syscall.GetFileInformationByHandle(h, &i); err != nil {
		return nil, err
	}

	return &fileStat{
		CreationTime:   i.CreationTime,
		LastAccessTime: i.LastAccessTime,
		LastWriteTime:  i.LastWriteTime,
		FileSizeHigh:   i.FileSizeHigh,
		FileSizeLow:    i.FileSizeLow,
		Nlink:          i.NumberOfLinks,
		vol:            i.VolumeSerialNumber,
		idxhi:          i.FileIndexHigh,
		idxlo:          i.FileIndexLow,
	}, nil
}

func sameFile(fs1, fs2 *fileStat) bool {
	return sameFilesystem(fs1, fs2) && fs1.idxhi == fs2.idxhi && fs1.idxlo == fs2.idxlo
}

func sameFilesystem(fs1, fs2 *fileStat) bool {
	return fs1.vol == fs2.vol
}
